package cn.autumnorange.app.util.consumer.controller;

import cn.autumnorange.app.common.consumerproducer.util.ClassUtil;
import cn.autumnorange.app.common.dto.ResultDto;

import cn.autumnorange.app.common.rpc.lock.RPCIdempotentLockTarget;
import cn.autumnorange.app.util.api.TimeService;
import cn.autumnorange.app.util.api.dto.ChildrenDto;
import cn.autumnorange.app.util.api.dto.ChildrenDto2;
import cn.autumnorange.app.util.api.dto.OrderDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;

@Slf4j
@RestController
public class UtilController implements TimeService {


    @Autowired
   private TimeService timeService;
//    @Autowired
//    private PaymentNotifySender sender;

    public TimeService getTimeService() {
        return timeService;
    }

    public void setTimeService(TimeService timeService) {
        this.timeService = timeService;
    }

    public ResponseEntity<ResultDto<String>> timestampToYYMMDD(
            @PathVariable(value = "timestamp") long timestamp) {
        return timeService.timestampToYYMMDD(timestamp);
    }

    /**
     * 类,相关接口指定的方法是否有该指定的注解
     *
     * @param className
     * @param methodName
     * @return
     */
    @Override
    public ResponseEntity<ResultDto<String>> getAnnotation(@PathVariable(value = "className") String className, @PathVariable(value = "methodName") String methodName, @PathVariable(value = "annotationName") String annotationName) {
//        try{
//            Thread.sleep(600000);
//        }catch (Exception e){
//
//        }
        Annotation checkAnnotation=checkAnnotation(className, methodName, annotationName, true, true);
//       boolean checkAnnotation= checkAnnotation("cn.autumnorange.app.util.consumer.controller.RPCIdempotentLockTargetCheckTest3", "testvoid", "cn.autumnorange.app.common.rpc.lock.RPCIdempotentLockTarget", true, true);
        RPCIdempotentLockTarget rpcIdempotentLockTarget=(RPCIdempotentLockTarget)checkAnnotation;

        return timeService.getAnnotation(className,methodName,annotationName);
//        return  ResponseEntity.ok().body(ResultDto.createDataResult(rpcIdempotentLockTarget.rpcLock()));
    }

    @Override
    public ResponseEntity<ResultDto<OrderDto>> updOrder(@RequestBody OrderDto orderDto) throws Exception{
//
//       try{
//           Thread.sleep(600000);
//       }catch (Exception e){
//
//       }
//        sender.sender("支付订单号："+System.currentTimeMillis());

        return timeService.updOrder(orderDto);
    }


    public static void main(String[] args) throws IllegalAccessException {

        Method[] methods = UtilController.class.getMethods();


//        boolean hascheckAnnotation = checkAnnotation("cn.autumnorange.app.util.consumer.controller.UtilController", "timestampToYYMMDDlongorg.springframework.http.ResponseEntity", "cn.autumnorange.app.common.rpc.lock.RPCIdempotentLockTarget", true, true);
//        boolean hascheckAnnotation = checkAnnotation("cn.autumnorange.app.util.consumer.controller.RPCIdempotentLockTargetCheckTest1", "testvoid", "cn.autumnorange.app.common.rpc.lock.RPCIdempotentLockTarget", true, true);
//        boolean hascheckAnnotation = checkAnnotation("cn.autumnorange.app.util.consumer.controller.RPCIdempotentLockTargetCheckTest2", "testvoid", "cn.autumnorange.app.common.rpc.lock.RPCIdempotentLockTarget", true, true);
//          Annotation annotation=checkAnnotation("cn.autumnorange.app.util.consumer.controller.RPCIdempotentLockTargetCheckTest3", "testvoid", "cn.autumnorange.app.common.rpc.lock.RPCIdempotentLockTarget", true, true);

//cn.autumnorange.app.util.consumer.controller.RPCIdempotentLockTargetCheckTest1
//        System.out.println(annotation);
        OrderDto orderDto=new OrderDto();

        ChildrenDto childrenDto= new ChildrenDto();
        childrenDto.setIdc("111");
        ChildrenDto childrenDto2= new ChildrenDto();
        childrenDto2.setIdc("222");
        orderDto.setChildrenDto(childrenDto);
        ChildrenDto2 childrenDto2Obj=new ChildrenDto2();
        childrenDto2Obj.setIdc("childrenDto2Obj");
        childrenDto.setChildrenDto2(childrenDto2Obj);
        childrenDto.setChildrenDto(childrenDto2);
//        ChildrenDto2 childrenDto2res=(ChildrenDto2)ClassUtil.getTargetObjByCheckClass(ChildrenDto.class,orderDto);
//        System.out.println(childrenDto2res.getIdc());
        ArrayList<String> arrayList= new ArrayList<String>();
        arrayList.add("childrenDto");
        arrayList.add("childrenDto2");

        ChildrenDto2 c =(ChildrenDto2)ClassUtil.getFieldObjByClass(orderDto,arrayList);
        System.out.println(c.getIdc());

    }

    /**
     * @param classesName
     * @param methodName
     * @param annotationName
     * @return
     */
    public static Annotation checkAnnotation(String classesName, String methodName, String annotationName, boolean checkInterface, boolean checkParent) {
        Annotation rpcIdempotentLockTarget =null;
        if (StringUtils.trimToEmpty(classesName).equals("")) {
            return null;
        }
        Class classes = null;
        Method[] methods = null;
        try {
            classes = Class.forName(classesName);
        } catch (ClassNotFoundException e) {
            //日志
        }
        if(classes==null){
            return null;
        }
        methods = classes.getMethods();
        if (methods != null) {
            for (Method method : methods) {
                //匹配注解方法是否存在指定的类方法中 匹配方式 方法名+方法参数+方法返回参数 组成字符串匹配
                String methodMsg = getMethodAllMSG(method);
//                timestampToYYMMDDlongorg.springframework.http.ResponseEntity
                if (methodMsg.equals(methodName)) {
//          rpcIdempotentLockTarget
                    Class annotationClass = null;
                    try {
                        annotationClass = Class.forName(annotationName);
                    } catch (ClassNotFoundException e) {
                        //日志
                    }
                    rpcIdempotentLockTarget =
                            method.getAnnotation(annotationClass);
                    if (rpcIdempotentLockTarget instanceof RPCIdempotentLockTarget) {
//                            result = ((RPCIdempotentLockTarget) rpcIdempotentLockTarget).rpcLock();
                        return rpcIdempotentLockTarget;
                        }
                }
            }
        }
        if (checkInterface) {
            Class<?>[] interfaces = classes.getInterfaces();
            for (Class classInterface : interfaces) {
                rpcIdempotentLockTarget = checkAnnotation(classInterface.getName(), methodName, annotationName, checkInterface, checkParent);
                if (rpcIdempotentLockTarget!=null ) {
                    return rpcIdempotentLockTarget;
                }
            }
        }
        if (checkParent) {
            Class<?> superclass = classes.getSuperclass();
          if(superclass!=null){
              rpcIdempotentLockTarget = checkAnnotation(superclass.getName(), methodName, annotationName, checkInterface, checkParent);
                if (rpcIdempotentLockTarget!=null ) {
                    return rpcIdempotentLockTarget;
                }
            }
        }
        return rpcIdempotentLockTarget;
    }

    public static String getMethodAllMSG(Method method) {
        if (method == null) {
            return null;
        }
        String methodMsg = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        String paramTypeClassStr = "";
        for (Class<?> paramTypeClass : parameterTypes) {
            paramTypeClassStr += paramTypeClass.getName();
        }
        methodMsg += paramTypeClassStr;
        Class<?> returnTYpes = method.getReturnType();
        methodMsg += returnTYpes.getName();

        return methodMsg;
    }
}
